﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Media;

namespace MeasureTime
{
    /// <summary>
    /// Form for the interval.
    /// </summary>
    public partial class IntervalForm : Form
    {
        #region Constants.

        private const string INTERVAL_FORMAT    = "Interval (minutes) = {0}";
        private const string TICK_FORMAT        = "Tick interval (seconds) = {0}";

        private const int PROGRESS_BAR_STEP = 5;

        #endregion Constants.

        #region Private fields.

        private int interval_   = 1;
        private double tick_    = 0.1;
        private Dictionary<int, double> tickValues_ = new Dictionary<int, double>();

        #endregion Private fields.

        #region Constructors.

        /// <summary>
        /// Default constructor.
        /// </summary>
        public IntervalForm()
        {
            InitializeComponent();

            PlayIntervalSound = true;
            PlayTickSound = true;

            LoadTickValues();
        }

        #endregion Constructors.

        #region Private methods.

        /// <summary>
        /// Loads the tick values.
        /// </summary>
        private void LoadTickValues()
        {
            tickValues_.Add(0, 0.1);
            tickValues_.Add(1, 0.2);
            tickValues_.Add(2, 0.3);
            tickValues_.Add(3, 0.4);
            tickValues_.Add(4, 0.5);
            tickValues_.Add(5, 0.6);
            tickValues_.Add(6, 0.7);
            tickValues_.Add(7, 0.8);
            tickValues_.Add(8, 0.9);
            tickValues_.Add(9, 1);
            tickValues_.Add(10, 2);
            tickValues_.Add(11, 3);
            tickValues_.Add(12, 4);
            tickValues_.Add(13, 5);
            tickValues_.Add(14, 6);
            tickValues_.Add(15, 7);
            tickValues_.Add(16, 8);
            tickValues_.Add(17, 9);
            tickValues_.Add(18, 10);
            tickValues_.Add(19, 11);
            tickValues_.Add(20, 12);
            tickValues_.Add(21, 13);
            tickValues_.Add(22, 14);
            tickValues_.Add(23, 15);
        }

        #endregion Private methods.

        #region Events.

        /// <summary>
        /// Raised when the interval was changed.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnIntervalChanged(object sender, EventArgs e)
        {
            this.interval_ = this.trackInterval_.Value + 1;
            this.intervalLabel_.Text = string.Format(INTERVAL_FORMAT, this.interval_);
        }

        /// <summary>
        /// Raised when the tick was changed.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnTickChanged(object sender, EventArgs e)
        {
            this.tick_ = this.tickValues_[this.trackTick_.Value];
            this.tickLabel_.Text = string.Format(TICK_FORMAT, this.tick_);
        }

        /// <summary>
        /// On start.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnStart(object sender, EventArgs e)
        {
            if (this.tick_ == 0 || this.interval_ == 0)
            {
                MessageBox.Show("Please select values for interval and tick.", "Invalid values", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            UpdateFormState(false);

            // Set the parameters for timers
            checkTick_.Interval = (int)(this.tick_ * 1000);         // from seconds to milisecs
            checkInterval_.Interval = this.interval_ * 60 * 1000;   // from minutes => milisecs
            progressBarTimer_.Interval = PROGRESS_BAR_STEP * 1000;  // 5 seconds

            UpdateFormText();
       
            // Set the parameters for the progress bar
            this.progressBar_.Minimum = 0;
            this.progressBar_.Maximum = this.interval_ * 60;
            this.progressBar_.Step = PROGRESS_BAR_STEP;
            this.progressBar_.Enabled = true;

            // Enable timers
            checkTick_.Enabled = true;            
            progressBarTimer_.Enabled = true;
            checkInterval_.Enabled = true;
        }

        /// <summary>
        /// On stop.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnStop(object sender, EventArgs e)
        {
            trackInterval_.Value = 0;
            trackTick_.Value = 0;
            progressBar_.Value = 0;
            
            checkInterval_.Enabled = false;
            checkTick_.Enabled = false;
            progressBarTimer_.Enabled = false;

            Text = "Measure Time";
            
            UpdateFormState(true);
        }

        /// <summary>
        /// Interval time passes
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnTimePasses(object sender, EventArgs e)
        {
            MakeTickSound();
            MakeIntervalSound();

            // Update 
            progressBar_.PerformStep();

            // the entire interval of the exercise elapsed
            checkInterval_.Enabled      = false;
            checkTick_.Enabled          = false;
            progressBarTimer_.Enabled   = false;

            MessageBox.Show(String.Format("It passed {0} minutes.", this.interval_));
        }

        /// <summary>
        /// Tick passes
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnTickElapsed(object sender, EventArgs e)
        {
            MakeTickSound();
        }

        /// <summary>
        /// Update the progress bar.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnUpdateProgressBar(object sender, EventArgs e)
        {
            progressBar_.PerformStep();
        }

        /// <summary>
        /// Raised when the play interval checkbox is checked.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnPlayIntervalSound(object sender, EventArgs e)
        {
            PlayIntervalSound = checkBoxPlayIntervalSound_.Checked;
        }

        /// <summary>
        /// Raised when the play tick checkbox is checked.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">e</param>
        private void OnPlayTickSound(object sender, EventArgs e)
        {
            PlayTickSound = checkBoxPlayTickSound_.Checked;
        }

        #endregion Events.

        #region Private (helper) methods.

        /// <summary>
        /// Plays the interval sound.
        /// </summary>
        private void MakeIntervalSound()
        {
            if (PlayIntervalSound)
            {
                MakeSound(Properties.Resources.tada);
            }
        }

        /// <summary>
        /// Plays the tick sound
        /// </summary>
        private void MakeTickSound()
        {
            if (PlayTickSound)
            {   
                MakeSound(Properties.Resources.IWindows_Ding);
            }
        }

        /// <summary>
        /// Makes sound.
        /// </summary>
        private static void MakeSound(System.IO.UnmanagedMemoryStream wavStream)
        {
            using (SoundPlayer player = new SoundPlayer(wavStream))
            {
                player.Play();
            }
        }

        /// <summary>
        /// Updates the form state
        /// </summary>
        /// <param name="enable">true to enable controls, false otherwise</param>
        private void UpdateFormState(bool enable)
        {
            buttonStart_.Enabled = enable;
            trackInterval_.Enabled = enable;
            trackTick_.Enabled = enable;
            checkBoxPlayIntervalSound_.Enabled = enable;
            checkBoxPlayTickSound_.Enabled = enable;

            buttonStop_.Enabled = !enable;
        }

        /// <summary>
        /// Updates the form text
        /// </summary>
        private void UpdateFormText()
        {
            this.Text = String.Format("Tick = {0} ms; Interval = {1} ms; ProgressBar = {2} ms",
                checkTick_.Interval, checkInterval_.Interval, progressBarTimer_.Interval);
        }

        #endregion Private (helper) methods.

        #region Private properties.

        /// <summary>
        /// Property for playing interval sound.
        /// </summary>
        private bool PlayIntervalSound { get; set; }

        /// <summary>
        /// Property for playing tick sound.
        /// </summary>
        private bool PlayTickSound { get; set; }

        #endregion Private properties.
    }
}
